package 栈;

import java.util.Stack;

/**
 * https://leetcode-cn.com/problems/evaluate-reverse-polish-notation
 *
 * 前缀表达式的运算符位于两个相应操作数之前，前缀表达式又被称为前缀记法或波兰式
 *
 * 有效的运算符包括+,-,*,/。每个运算对象可以是整数，也可以是另一个逆波兰表达式。
 * 说明：
 * 整数除法只保留整数部分。
 * 给定逆波兰表达式总是有效的。换句话说，表达式总会得出有效数值且不存在除数为 0 的情况。
 * 逆波兰表达式：
 * 逆波兰表达式是一种后缀表达式，所谓后缀就是指算符写在后面。
 * 平常使用的算式则是一种中缀表达式，如 ( 1 + 2 ) * ( 3 + 4 ) 。
 * 该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
 * 逆波兰表达式主要有以下两个优点：
 * 去掉括号后表达式无歧义，上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
 * 适合用栈操作运算：遇到数字则入栈；遇到算符则取出栈顶两个数字进行计算，并将结果压入栈中。
 *
 * 解题思路：
 * 遍历字符串，若遇到数字将数字入栈，若遇到符号，从栈中取出前面两个元素进行计算，计算完成后将结果入栈。
 * 遍历结束，从栈中取出栈顶的值。
 *
 */
public class _150_逆波兰表达式求值 {
    public static void main(String[] args) {
        String[] str1 = {"2", "1", "+", "3", "*"};
        String[] str2 = {"4", "13", "5", "/", "+"};
        String[] str3 = {"10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"};

        System.out.println(evalRPN(str1));
        System.out.println(evalRPN(str2));
        System.out.println(evalRPN(str3));
    }

    public static int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack();
        for (String token : tokens) {
            Integer pop1;
            Integer pop2;
            switch (token) {
                case "+":
                    pop2 = stack.pop();
                    pop1 = stack.pop();
                    stack.push(pop1 + pop2);
                    break;
                case "-":
                    pop2 = stack.pop();
                    pop1 = stack.pop();
                    stack.push(pop1 - pop2);
                    break;
                case "*":
                    pop2 = stack.pop();
                    pop1 = stack.pop();
                    stack.push(pop1 * pop2);
                    break;
                case "/":
                    pop2 = stack.pop();
                    pop1 = stack.pop();
                    stack.push(pop1 / pop2);
                    break;
                default:
                    stack.push(Integer.parseInt(token));
                    break;
            }
        }
        return stack.pop();
    }
}
